﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using WooCoo.ObjectModel;
using WooCoo.ObjectModel.ManagedProperty;
using WooCoo.Tools;

namespace WooCoo.Data.EF
{
    public abstract class EntityRepositoryBase<T> : IRepository, IRepository<T>
        where T : Entity
    {
        /// <summary>
        /// 数据库连接配置
        /// </summary>
        public virtual string DatabaseConfigName { get; set; }

        #region IRepository<T>
        public virtual IQueryable<T> AsQueryable()
        {
            DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T));

            return db.DbContext.Set<T>();

        }

        public virtual T Find(params object[] keys)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                return db.DbContext.Set<T>().Find(keys);
            }
        }

        public virtual int Add(T entity)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                db.DbContext.Set<T>().Add(entity);
                return db.Commit();
            }
        }

        public virtual int Remove(T entity)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                DbEntityEntry<T> entry = db.DbContext.Entry<T>(entity);
                entry.State = EntityState.Deleted;
                db.DbContext.Set<T>().Remove(entity);
                return db.Commit();
            }
        }

        public virtual int RemoveRange(System.Linq.Expressions.Expression<Func<T, bool>> predicate)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                //db.DbContext.Set<T>().RemoveRange();
                return db.Commit();
            }
        }

        public virtual int Update(T entity)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                db.DbContext.Set<T>().Attach(entity);
                db.DbContext.Entry<T>(entity).State = EntityState.Modified;
                return db.Commit();
            }
        }
        #endregion

        #region IRepository
        IQueryable IRepository.AsQueryable()
        {
            return this.AsQueryable();
        }
        /// <summary>
        /// 只支持单主键
        /// </summary>
        /// <param name="keys"></param>
        /// <returns></returns>
        object IRepository.Find(params object[] keys)
        {
            if (keys.Count() > 1)
                throw Error.NotSupported("不支持主键数大于1的查询！");
            var ps = PropertyInfoRepository.Instance.GetPropertyInfoSet(typeof(T));
            var pi = ps.GetProperties().FirstOrDefault(o=>o.Index==0);
            keys[0] = TypeHelper.CoerceValue(pi.Type, keys[0]);
            return this.Find(keys);
        }

        int IRepository.Add(object entityOrList)
        {
            if (entityOrList is T)
            {
                //entity
                return this.Add((T)entityOrList);
            }
            else
            {
                //List
                foreach (var item in (IList)entityOrList)
                {
                    using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
                    {
                        this.Add((T)item);
                        db.Commit();
                    }
                }
                return ((IList)entityOrList).Count;
            }

        }

        int IRepository.Remove(object entity)
        {
            return this.Remove((T)entity);
        }

        int IRepository.Update(object entity)
        {
            return this.Update((T)entity);
        }

        public int SaveChanges(object entityOrList)
        {
            using (DbContextManager db = DbContextManager.GetManager(this.DatabaseConfigName, typeof(T)))
            {
                int i = 0;
                var entity = entityOrList as Entity;
                if (entity != null)
                {
                    if (entity.Status == PersistenceStatus.New)
                        return this.Add((T)entity);
                    else if (entity.Status == PersistenceStatus.Deleted)
                        return this.Remove((T)entity);
                    else if ((entity as ITrackStatus).IsDirty)
                        return this.Update((T)entity);
                }
                else if (entityOrList is IEnumerable)
                {

                    foreach (var item in entityOrList as System.Collections.IEnumerable)
                    {
                        i += this.SaveChanges(item);
                    }
                }
                else
                    Error.NotSupported(string.Format("该实体类型:{0}不符合Entity约束", entityOrList.GetType()));
                db.Commit();
                return i;
            }
        }
        #endregion

        TransactionManager IUnitOfWork.TransactionManager
        {
            get
            {
                return DbContextManager.GetManager(this.DatabaseConfigName, typeof(T));
            }
        }
    }
}
